cmake_minimum_required(VERSION 2.8)
project (my_test)

## set cmake modules path
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)

## Directory variables
set(INC_DIR ${PROJECT_SOURCE_DIR}/include)
set(SRC_DIR ${PROJECT_SOURCE_DIR}/src)
set(TOOLS_DIR ${PROJECT_SOURCE_DIR}/tools)
set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib)

## output directories
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

## OPTIONS
OPTION(BUILD_ANDROID "whether to build on android platform" OFF)
OPTION(BUILD_IOS "whether to build on ios platform" OFF)
OPTION(USE_STATIC "whether to build static library" OFF)
OPTION(BUILD_I386 "whether to build with i386" OFF)
OPTION(USE_C++11 "Android can read caffe prototxt file" ON)

message(STATUS "USE_C++11 : " ${USE_C++11})

## setting Platform and processor
if (BUILD_ANDROID)
    if(ARM_ARCH MATCHES ARMV7)
        set(ANDROID_TOOLCHAIN_ROOT /home/android-toolchain-armv7)
        set(CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/sysroot")
        set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
        set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
        set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
        set(CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/arm-linux-androideabi-gcc")
        set(CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/arm-linux-androideabi-g++")
        set(CMAKE_SYSTEM_PROCESSOR armv7)
    elseif(ARM_ARCH MATCHES ARM64)
        set(ANDROID_TOOLCHAIN_ROOT /home/android-toolchain-arm64)
        set(CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/sysroot")
        set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
        set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
        set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
        set(CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/aarch64-linux-android-gcc")
        set(CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/aarch64-linux-android-g++")
        set(CMAKE_SYSTEM_PROCESSOR aarch64)
    endif()
endif()
if (BUILD_IOS)
    set(CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk)
    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
    if(ARM_ARCH MATCHES ARMV7)
        set(CMAKE_SYSTEM_PROCESSOR armv7)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch armv7")
    elseif(ARM_ARCH MATCHES ARM64)
        set(CMAKE_SYSTEM_PROCESSOR aarch64)
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch arm64")
    endif()
endif()
if (BUILD_ARM)
    if(ARM_ARCH MATCHES ARMV7)
        set(ARMLINUX_TOOLCHAIN_ROOT /usr/bin)
        set(CMAKE_C_COMPILER "${ARMLINUX_TOOLCHAIN_ROOT}/arm-linux-gnueabihf-gcc")
        set(CMAKE_CXX_COMPILER "${ARMLINUX_TOOLCHAIN_ROOT}/arm-linux-gnueabihf-g++")
        set(CMAKE_SYSTEM_PROCESSOR armv7)
    elseif(ARM_ARCH MATCHES ARM64)
        set(ARMLINUX_TOOLCHAIN_ROOT /usr/bin)
        set(CMAKE_C_COMPILER "${ARMLINUX_TOOLCHAIN_ROOT}/aarch64-linux-gnu-gcc")
        set(CMAKE_CXX_COMPILER "${ARMLINUX_TOOLCHAIN_ROOT}/aarch64-linux-gnu-g++")
        set(CMAKE_SYSTEM_PROCESSOR aarch64)
    endif()
endif()

message(STATUS "CMAKE_CXX INFO: ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS "CMAKE_C INFO: ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}")
message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")

###### Architecture setting #####
if (USE_CUDA)
    find_package(CUDA "7.0")
    find_package(CUDNN)
    if (CUDA_FOUND AND CUDNN_FOUND)
        set(ARCH CUDA)
    else()
        message(FATAL_ERROR "You set USE_CUDA, but could not found CUDA or CUDNN.")
    endif()
elseif (USE_OCL)
    find_package(OpenCL REQUIRED)
    if (OpenCL_FOUND)
        set(ARCH OCL)
    else()
        message(FATAL_ERROR "You set USE_OCL, but could not found OpenCL.")
    endif()
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES x86* OR CMAKE_SYSTEM_PROCESSOR MATCHES i.86)
    set(ARCH X86)
    #set(AVX_ENABLED_FLAG "-mavx")
    #set(FMA_ENABLED_FLAG "-mfma")
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES AMD64) #WINDOWS
    set(ARCH X86)
    #set(AVX_ENABLED_FLAG "/arch:AVX")
    #set(FMA_ENABLED_FLAG "/arch:AVX2")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES arm* OR CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
    set(ARCH ARM)
endif()

if (BUILD_I386)
    set(IS_I386 "-m32")
endif()
if (DEBUG)
    set(CXX_COMMON_FLAGS "-O0 -g")
else()
    set(CXX_COMMON_FLAGS "-O3")
endif()

###### Compiler flag setting ######
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
    if (USE_STATIC)
        set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -fPIC -static -fopenmp ${IS_I386}")
    else()
        set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -fPIC -fopenmp ${IS_I386}")
    endif()
    if(USE_C++11)
        set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -std=c++11")
    else()
        set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -std=c++0x")
    endif()
    set(WARNING_ENABLED_FLAGS "-W -WALL")
    if(-mfloat-abi MATCHES hard)
        set(MFLOAT_ABI "hard")
    else()
        set(MFLOAT_ABI "softfp")
    endif()

    if (ARCH MATCHES ARM)
        # set neon flag
        set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -mfloat-abi=${MFLOAT_ABI} -mfpu=neon -ftree-vectorize -flax-vector-conversions")
        # set arm half flag
        set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -mfp16-format=ieee")
    endif ()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -fPIC ${IS_I386}")
    if(USE_C++11)
        set(CXX_COMMON_FLAGS "${CXX_COMMON_FLAGS} -std=c++11 -stdlib=libc++")
    endif()
    set(CMAKE_MACOSX_RPATH ON)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
    if (NOT BUILD_WINDOWS)
        set(BUILD_WINDOWS ON)
    endif()
    set(CXX_COMMON_FLAGS "/O2")
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
    set(CMAKE_IMPORT_LIBRARY_PREFIX "lib")
    #set(CMAKE_IMPORT_LIBRARY_SUFFIX ".dll")
    set(CMAKE_SHARED_LIBRARY_PREFIX "lib")
    #set(CMAKE_SHARED_LIBRARY_SUFFIX ".dll")
    set(CMAKE_STATIC_LIBRARY_PREFIX "lib")
    #set(CMAKE_STATIC_LIBRARY_SUFFIX ".lib")
else()
    message(FATAL_ERROR, "Error: The compiler is not supported")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_COMMON_FLAGS}")

message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
message(STATUS "CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}")

message(STATUS "CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}")


####### set target system #######
set(TARGET_OS ${CMAKE_HOST_SYSTEM_NAME})
if(CMAKE_HOST_SYSTEM_NAME MATCHES Linux*)
    set(TARGET_OS linux)
elseif(CMAKE_HOST_SYSTEM_NAME MATCHES Darwin*)
    set(TARGET_OS mac)
elseif(CMAKE_HOST_SYSTEM_NAME MATCHES WIN*)
    set(TARGET_OS windows)
endif()
if(BUILD_IOS)
    set(TARGET_OS ios)
elseif(BUILD_ANDROID)
    set(TARGET_OS android)
endif()
message(STATUS "TARGET_OS : ${TARGET_OS}")

## set link lib name and output lib name
if(CMAKE_SYSTEM_PROCESSOR MATCHES i.86 OR BUILD_I386)
    set(LINK_LIB_DEP dep_${TARGET_OS}_x86${LIB_NAME_SUFFIX})
    set(TEST_LIB_NAME test_${TARGET_OS}_x86${LIB_NAME_SUFFIX})
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES x86*)
    set(LINK_LIB_DEP dep_${TARGET_OS}_x86_64${LIB_NAME_SUFFIX})
    set(TEST_LIB_NAME test_${TARGET_OS}_x86_64${LIB_NAME_SUFFIX})
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES armv7*)
    set(LINK_LIB_DEP dep_${TARGET_OS}_armv7${LIB_NAME_SUFFIX})
    set(TEST_LIB_NAME test_${TARGET_OS}_armv7${LIB_NAME_SUFFIX})
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES aarch64)
    set(LINK_LIB_DEP dep_${TARGET_OS}_arm64${LIB_NAME_SUFFIX})
    set(TEST_LIB_NAME test_${TARGET_OS}_arm64${LIB_NAME_SUFFIX})
endif()
message(STATUS "TEST_LIB_NAME: ${TEST_LIB_NAME}")

##compile libtest.so  use definition control src
if(BUILD_ANDROID)
    ADD_DEFINITIONS(-DTEST_BUILD_ANDROID)
endif()
ADD_SUBDIRECTORY(${SRC_DIR})

##link examples
if (NOT BUILD_ANDROID AND NOT BUILD_IOS)
    ADD_SUBDIRECTORY(${TOOLS_DIR})
endif()
